﻿/*
 * ESC/POS客户端 普通模式
 */
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ACEPAPI
{
    /// <summary>
    /// ESC/POS客户端 - 使用System.Net.Sockets.Socket
    /// </summary>
    public class EPClientSocket : EPClientBase
    {
        /// <summary>
        /// 当前Socket
        /// </summary>
        public Socket Socket { get; set; }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="IPAdd">打印机IP地址</param>
        /// <param name="Port">打印机端口地址(默认9100)</param>
        public EPClientSocket(string ipAdd, int ipPort = 9100)
        {
            //检测IP地址与端口
            IPAddress _IPAdd;
            if (!IPAddress.TryParse(ipAdd, out _IPAdd))
            {
                throw new ApplicationException("指定的打印机没有正确设置ip地址，无法打印");
            }
            IPAddress = _IPAdd;
            if (ipPort > 0 && ipPort <= 65535)
            {
                IPPort = ipPort;
            }
            else
            {
                throw new ApplicationException("指定的打印机没有正确设置端口地址，无法打印");
            }
        }

        /// <summary>
        /// 析构函数
        /// </summary>
        ~EPClientSocket()
        {
            Dispose();
        }

        /// <summary>
        /// 关闭打印机连接
        /// </summary>
        public void CloseConnect()
        {
            if (Socket != null)
            {
                Socket.Disconnect(true);
                Socket.Dispose();
                Socket = null;
            }
        }

        /// <summary>
        /// Socket连接
        /// </summary>
        public void Connect()
        {
            //设置Socket
            try
            {
                if (Socket != null && Socket.Connected)
                {
                    Socket.Disconnect(false);
                    Socket.Dispose();
                    Socket = null;
                }
                Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                Socket.NoDelay = true;
                Socket.SendTimeout = 3000;
                Socket.ReceiveTimeout = 3000;
                Socket.Connect(IPAddress, IPPort);
            }
            catch (SocketException)
            {
                throw;
            }
        }

        /// <summary>
        /// Socket重新连接
        /// </summary>
        public void Reconnect()
        {
            try
            {
                if (Socket != null)
                {
                    if (Socket.Connected)
                    {
                        Socket.Disconnect(false);
                    }
                    Socket.Dispose();
                    Socket = null;
                }
                Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                Socket.NoDelay = true;
                Socket.SendTimeout = 3000;
                Socket.ReceiveTimeout = 3000;
                Socket.Connect(IPAddress, IPPort);
            }
            catch (SocketException)
            {
                throw;
            }
        }

        /// <summary>
        /// 释放Socket资源
        /// </summary>
        public override void Dispose()
        {
            Socket?.Disconnect(true);
            Socket?.Close();
            Socket?.Dispose();
            Socket = null;
        }

        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="sendBytes">数据内容</param>
        public void SendBytes(byte[] sendBytes)
        {
            if (Socket == null || !Socket.Connected)
            {
                Reconnect();
            }
            try
            {
                Socket.Send(sendBytes);
            }
            catch (SocketException)
            {
                CloseConnect();
            }
        }

        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="content">数据内容</param>
        /// <param name="waitResponse">是否等待返回数据</param>
        /// <param name="waitTimeoutSeconds">等待超时时长(毫秒)</param>
        /// <returns>接收到的数据</returns>
        public byte[] SendBytes(byte[] sendBytes, bool waitResponse, int waitTimeoutSeconds)
        {
            if (Socket == null || !Socket.Connected)
            {
                Reconnect();
            }

            try
            {
                Socket.Send(sendBytes);
                if (waitResponse)
                {
                    return ReadBytes(waitTimeoutSeconds);
                }
            }
            catch (SocketException)
            {
                CloseConnect();
                throw;
            }
            return new byte[0];
        }
        
        /// <summary>
        /// 接收数据
        /// </summary>
        /// <param name="timeoutSeconds">等待超时时长</param>
        /// <returns>接收到的数据</returns>
        public byte[] ReadBytes(int timeoutSeconds)
        {
            try
            {
                Socket.ReceiveTimeout = timeoutSeconds;
                byte[] buffer = new byte[64];
                int nums = Socket.Receive(buffer);
                if (nums <= 0)
                {
                    return new byte[0];
                }
                else
                {
                    byte[] result = new byte[nums];
                    Array.Copy(buffer, result, nums);
                    return result;
                }
            }
            catch (SocketException)
            {
                throw;
            }
        }

        
    }
}
